import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import junit.framework.TestCase;

import org.junit.Test;

/**
 * JUnit test class for the remember program.
 * @author Fletcher Johnson
 *
 */
public class RememberTest extends TestCase{
	
	private Remember rmb = Remember.getInstance();
	
	protected void setUp(){
		rmb.clearItems();
	}
	
	
	/**
	 * Add a single item and ensure it was added properly.
	 */
	@Test
	public void testAddOneNoPrevious() {
		String item = "/home/fletcher";
		try{
			rmb.addItem(item,false);
			List<String> result = rmb.listSaved();
			assertTrue(result != null);
			assertTrue(result.size() != 0);
			assertTrue(result.get(0).equals(item));
		}catch(IOException e){
			e.printStackTrace();
			fail("IOException failure: " + e.getMessage());
		}
	}
	
	
	/**
	 * Add three items and assure they were added properly.
	 */
	@Test
	public void testAddThreeNoPrevious(){
		List<String> items = new ArrayList<String>();
		items.add("/home/fletcher/");
		items.add("~/workspace1");
		items.add("document.tar");
		
		try{
			for(String item : items)
				assertTrue(rmb.addItem(item,false));
			
			List<String> result = rmb.listSaved();
			assertFalse(result == null);
			assertFalse(result.size() == 0);
			assertTrue(result.get(0),result.get(0).equals("/home/fletcher/"));
			assertTrue(result.get(1),result.get(1).equals("~/workspace1"));
			assertTrue(result.get(2),result.get(2).equals("document.tar"));
		}catch(IOException e){
			e.printStackTrace();
			fail("IOException failure: " + e.getMessage());
		}
	}
	
	
	/**
	 * Attempt to read an item that does not exist.
	 */
	@Test
	public void testNoneRequest() throws IOException{
		assertTrue(rmb.readSaved(0) == null);
	}
	
	
	/**
	 * Attempt to read an item that does not exist (higher index).
	 */
	@Test
	public void testNoneRequest2() throws IOException{
		assertFalse(rmb.readSaved(4) != null);
	}
	
	
	/**
	 * Add an item then request for an invalid index, then check that
	 * the first added item still exists.
	 */
	@Test
	public void testAddBadRequest() throws IOException{
		assertTrue(rmb.addItem("/home/fletcher",false));
		assertTrue(rmb.listSaved() != null);
		assertTrue(rmb.readSaved(2) == null);
		assertTrue(rmb.listSaved() != null);
		assertTrue(rmb.listSaved().get(0), rmb.listSaved().get(0).equals("/home/fletcher"));
	}
	
	 
	/**
	 * Add an item and then do a number of bogus index requests. Check that
	 * the added item is still there.
	 */
	@Test
	public void testAddBadRequest2() throws IOException{
		assertTrue(rmb.addItem("/home/fletcher",false));
		assertFalse(rmb.listSaved() == null);
		assertTrue(rmb.readSaved(2) == null);
		assertTrue(rmb.readSaved(8) == null);
		assertTrue(rmb.readSaved(100) == null);
		assertFalse(rmb.listSaved() == null);
		assertTrue(rmb.listSaved().get(0), rmb.listSaved().get(0).equals("/home/fletcher"));
	}
	
	
	/**
	 * Add an item and then remove it by requesting it.
	 */
	@Test
	public void testAddRemove() throws IOException{
		String result;
		String item = "/home/fletcher";
		
		//add item
		assertTrue(rmb.addItem(item,false));
		assertTrue(rmb.listSaved().get(0),rmb.listSaved().get(0).equals(item));
		
		//request item
		result = rmb.readSaved(0);
		assertTrue(result,result.equals(item));
		
		//Item should no longer exist.
		assertTrue(rmb.listSaved() == null);
	}
	
	
	/**
	 * Add an item then remove it by requesting it and then add it again.
	 */
	@Test
	public void testAddRemoveAdd() throws IOException{
		String result;
		
		//add item
		assertTrue(rmb.addItem("/home/fletcher",false));
		
		//request item
		result = rmb.listSaved().get(0);
		assertTrue(result.equals(rmb.readSaved(0)));
		
		//add item
		assertTrue(rmb.addItem("/home/fletcher",false));
		assertTrue(rmb.listSaved().get(0).equals("/home/fletcher"));
	}
	
	
	/**
	 * Add two items and then remove them by requesting them.
	 */
	@Test
	public void testAddAddRemoveRemove() throws IOException{
		String result;
		
		assertTrue(rmb.addItem("item1",false));
		assertTrue(rmb.addItem("item2",false));
		
		result = rmb.readSaved(0);
		assertTrue(result,result.equals("item1"));
		
		result = rmb.readSaved(0);
		assertTrue(result,result.equals("item2"));
	}
	
	
	/**
	 * Add an item and then remove it by requesting it. Do this 3 times.
	 */
	@Test
	public void testAddDeleteAddDeleteAddDelete() throws IOException{
		String item;
		String result;
		
		item = "item1";
		assertTrue(rmb.addItem(item,false));
		result = rmb.readSaved(0);
		assertTrue(result,result.equals(item));
		
		item = "item2";
		assertTrue(rmb.addItem(item,false));
		result = rmb.readSaved(0);
		assertTrue(result,result.equals(item));
		
		item = "item3";
		assertTrue(rmb.addItem(item,false));
		result = rmb.readSaved(0);
		assertTrue(result,result.equals(item));
		
		assertTrue(rmb.listSaved() == null);
	}
	
	
	/**
	 * Add four items and then remove them while checking that the indexes 
	 * which access files are updated. 
	 */
	@Test
	public void testIndexes() throws IOException{
		String result;
		String item1 = "item1";
		String item2 = "item2";
		String item3 = "item3";
		String item4 = "item4";
		String[] items = {item1,item2,item3,item4};
		
		for(String item : items) rmb.addItem(item,false);
		
		//shift items 3,4 down by reading item2.
		result = rmb.readSaved(1);
		assertTrue(result,result.equals(item2));
		
		//no items are shifted.
		result = rmb.readSaved(2);
		assertTrue(result,result.equals(item4));
		
		//shift item 3 down by reading item 1
		result = rmb.readSaved(0);
		assertTrue(result,result.equals(item1));
		
		result = rmb.readSaved(0);
		assertTrue(result,result.equals(item3));
	}
	
	
	/**
	 * Another index test, test removing items at the front of the
	 * history stack.
	 */
	@Test
	public void testIndexesRemoveFront() throws IOException{
		String result;
		String item1 = "item1";
		String item2 = "item2";
		String item3 = "item3";
		String item4 = "item4";
		String[] items = {item1,item2,item3,item4};
		
		for(String item : items) rmb.addItem(item,false);
		
		result = rmb.readSaved(0);
		assertTrue(result,result.equals(item1));
		result = rmb.readSaved(0);
		assertTrue(result,result.equals(item2));
		result = rmb.readSaved(0);
		assertTrue(result,result.equals(item3));
		result = rmb.readSaved(0);
		assertTrue(result,result.equals(item4));
	}
	
	
	/**
	 * Another index test, test removing items at the Back of the
	 * history stack.
	 */
	@Test
	public void testIndexesRemoveBack() throws IOException{
		String result;
		String item1 = "item1";
		String item2 = "item2";
		String item3 = "item3";
		String item4 = "item4";
		String[] items = {item1,item2,item3,item4};
		
		for(String item : items) rmb.addItem(item,false);
		
		result = rmb.readSaved(3);
		assertTrue(result,result.equals(item4));
		result = rmb.readSaved(2);
		assertTrue(result,result.equals(item3));
		result = rmb.readSaved(1);
		assertTrue(result,result.equals(item2));
		result = rmb.readSaved(0);
		assertTrue(result,result.equals(item1));
	}
	
	//Add tests here for adding files (i.e -f mode)
	//Add tests here for accessing files without removing them (i.e -k)
}	





